<?php

namespace SunAdmin\Service;

use SunAdmin\Common\TokenHelper;
use SunAdmin\Common\Utils;

use SunAdmin\Model\AccountGroupModel;
use SunAdmin\Model\AccountModel;
use SunAdmin\Model\MenusModel;
use SunAdmin\Service\Ws\FdUidBinding;
use SunAdmin\Service\Ws\SendMessage;
use think\Exception;
use think\facade\Cache;
use think\swoole\websocket\Event;

class AccountService {
	public static function login(string $username, string $password): array {
		if (!$username || !$password) {
			throw new \Exception('用户名或密码不能为空');
		}
		$user = AccountModel::where('username', $username)->find();
		
		if (!$user || !password_verify($password, $user->password)) {
			throw new \Exception('用户名或密码错误');
		}
		if ($user->status != 1) {
			throw new \Exception('账号已被禁用');
		}
		if (!$user['is_administrators']) {
			$accountGroup = AccountGroupModel::where('id', $user['group_id'])->find();
			if (!$accountGroup) {
				throw new \Exception('账号权限组有误');
			}
			if(!$accountGroup->status){
				throw new \Exception('账号权限组已被禁用');
			}
		}
		return [
			'token'     => TokenHelper::generate($user->id,'admin'),
			...$user->toArray(),
			'menusList' => self::getAccountMenusList($user->group_id),
		];
	}
	
	/**
	 * 获取管理员角色组列表
	 * @return array
	 */
	public static function getGroupList() {
		$list = AccountGroupModel::select()->toArray();
		return ['list' => $list];
	}
	
	/**
	 * 创建 编辑管理员角色组
	 */
	public static function editAccountGroup($data = []) {
		if (empty($data['name'])) {
			throw new \Exception("角色组名称不能为空");
		}
		$data['add_time'] = Utils::timeToStr();
		if (empty($data['id'])) {
			AccountGroupModel::create($data);
		} else {
			AccountGroupModel::update($data, ['id' => $data['id']]);
		}
		return true;
	}
	
	/**
	 * 删除角色组
	 * @param $groupId int 角色组id
	 */
	public static function deleteAccountGroup($groupId) {
		if (empty($groupId)) {
			throw new \Exception("参数groupId不能为空");
		}
		$group = AccountGroupModel::where('id', $groupId)->find();
		if (empty($group)) {
			throw new \Exception("角色组不存在或已删除");
		}
		$accountCount = AccountModel::where('group_id', $groupId)->count();
		if ($accountCount > 0) {
			throw new \Exception("无法删除该组,该角色组下存在[{$accountCount}]个管理员账号");
		}
		$group->delete();
		return true;
	}
	
	public static function getAccountList($where) {
		$list = AccountModel::when(isset($where['is_del']), function ($q) use ($where) {
			$q->where('is_del', $where['is_del']);
		})->with([
			'groupInfo' => function ($query) {
				$query->field('id,name');
			},
		])->select()->toArray();
		foreach ($list as &$item) {
			unset($item['password']);
			if ($item['is_administrators']) {
				$item['groupInfo'] = ['id' => 0, 'name' => '超级管理员'];
			}
		}
		return ['list' => $list];
	}
	
	public static function editAccount($data = []) {
		if (empty($data['username']) || empty($data['nickname'])) {
			throw new \Exception("用户名和昵称不能为空");
		}
		//校验密码
		if (!empty($data['password'])) {
			if ($data['password'] !== $data['passwordConfirm']) {
				throw new \Exception("两次密码输入不一致");
			}
			if (strlen($data['password']) < 6) {
				throw new \Exception("密码不能小于6位数");
			}
		}
		if (empty($data['id'])) {
			$data['is_administrators'] = 0;
			if (empty($data['group_id'])) {
				throw new \Exception("角色组不能为空");
			}
			//新增
			$isInUsername = AccountModel::where('username', $data['username'])->find();
			if (!empty($isInUsername)) {
				throw new \Exception("该账号已存在,不可重复添加");
			}
			if (empty($data['password'])) {
				throw new \Exception("密码不能为空");
			}
			AccountModel::create($data);
		} else {
			//编辑
			$isInUsername = AccountModel::where('username', $data['username'])->where('id', '<>', $data['id'])->find();
			if (!empty($isInUsername)) {
				throw new \Exception("该账号已存在,不可重复添加");
			}
			if (empty($data['password'])) {
				unset($data['password'], $data['passwordConfirm']);
			}else{
                $isEditPassword = true;
            }
			$account = AccountModel::where('id', $data['id'])->find();
			if ($account['is_administrators']) {
				$data['is_administrators'] = 1;
				$data['group_id'] = 0;
				if (!$account['status']) {
					throw new \Exception("超管账号状态不可编辑");
				}
			} else {
				if (empty($data['group_id'])) {
					throw new \Exception("角色组不能为空");
				}
			}
			$account->save($data);
            //修改密码后登录失效
            if (isset($isEditPassword)) {
               AccountService::accountOffLine($data['id']);
            }
		}
		return true;
	}
	
	public static function delAccount($accountId) {
		$account = AccountModel::where('id', $accountId)->find();
		if (empty($account)) {
			throw new \Exception("账号不存在");
		}
		if ($account->is_del) {
			throw new \Exception("账号已被删除,不用重复操作");
		}
		if ($account->is_administrators) {
			throw new \Exception("不可以对超级管理员账号进行操作");
		}
		$account->is_del = 1;
		$account->save();
		return true;
	}
	
	/**
	 * 获取该账号权限下的后台菜单数据
	 */
	public static function getAccountMenusList($accountGroupId) {
		if (!is_numeric($accountGroupId)) {
			throw new \Exception("管理员角色组有误");
		}
		$where = ['show' => 1];
		if ($accountGroupId == 0) { //超管角色组
			$menusList = MenusModel::where($where)->order('sort asc')->select()->toArray();
		} else {
			$accountGroup = AccountGroupModel::where('id', $accountGroupId)->find();
			if (empty($accountGroup)) {
				throw new \Exception("管理员角色组不存在");
			}
			$menusList = MenusModel::where('id', 'in', $accountGroup['menus_ids'])->where($where)->order('sort asc')->select()->toArray();
		}
		//组织树状结构
		$treeList = Utils::buildTree($menusList, 0);
		return $treeList;
	}

    /**
     * 将某个管理员踢下线
     */
    public static function accountOffLine($accountId) {
        //移除token
        TokenHelper::delete($accountId,'admin');
        //发送ws
        $sendMessage =  new SendMessage('admin');
        $sendMessage->toUidSendMsg($accountId,new Event('offLine'));
    }

    /**
     * 向所有管理员广播某个管理员上下线
     */
    public static function sendAllAdminOnlineStatus($fd,int $onlineStatus) {
        $sendMessage =  new SendMessage('admin');
        $fdUidBing = new FdUidBinding('admin');
        $uidList = $fdUidBing->getAllOnlineUids();
        foreach ($uidList as $uid) {
            $sendMessage->toUidSendMsg($uid,new Event('adminOnlineStatus',['uid'=>$fdUidBing->fdToUid($fd),'onlineStatus'=>$onlineStatus]));
        }
    }
}